package com.huajx.core.common;

import com.huajx.util.ReflectUtil;
import com.huajx.util.convert.Convert;

import java.io.Serializable;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Date;

public class Column implements Serializable {
    public static final String LOGIC_LIKE = " LIKE ";
    public static final String LOGIC_LIKE_LEFT = "  LIKE ";
    public static final String LOGIC_LIKE_RIGHT = " LIKE  ";
    public static final String LOGIC_GT = " > ";
    public static final String LOGIC_GE = " >= ";
    public static final String LOGIC_LT = " < ";
    public static final String LOGIC_LE = " <= ";
    public static final String LOGIC_EQUALS = " = ";
    public static final String LOGIC_NOT_EQUALS = " != ";

    public static final String LOGIC_IS_NULL = " IS NULL ";
    public static final String LOGIC_IS_NOT_NULL = " IS NOT NULL ";


    private String name;
    private Object value;
    private String logic = LOGIC_EQUALS;

    public static Column create(String name) {
        Column column = new Column();
        column.setName(name);
        return column;
    }

    public static Column create(String name, Object value) {
        Column column = new Column();
        column.setName(name);
        column.setValue(value);
        return column;
    }

    public static Column create(String name, Object value, String logic) {
        Column column = new Column();
        column.setName(name);
        column.setValue(value);
        column.setLogic(logic);
        return column;
    }

    public Column logic(String logic) {
        this.setLogic(logic);
        return this;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Object getValue() {
        return value;
    }

    public void setValue(Object value) {
        this.value = value;
    }

    public String getLogic() {
        return logic;
    }

    public void setLogic(String logic) {
        this.logic = logic;
    }

    public boolean isMustNeedValue() {
        return !LOGIC_IS_NULL.equals(getLogic())
                && !LOGIC_IS_NOT_NULL.equals(getLogic());
    }

    public <T> boolean valid(T t) {
        if (t == null) {
            return false;
        }

        if (value == null) {
            return true;
        }

        boolean flag = name.contains("&");

        if (flag) {
            String[] keys = name.split("&");
            for (String key : keys) {
                if (validOne(t, key)) {
                    return true;
                }
            }
            return false;
        } else {
            return validOne(t, name);
        }
    }

    private <T> boolean validOne(T t, String key) {
        Object obj = ReflectUtil.getFieldValue(t, key);

        if (obj == null) {
            return false;
        }

        boolean flag = false;

        if (logic.equals(LOGIC_LIKE)) {
            String s1 = Convert.toStr(obj);
            String s2 = Convert.toStr(value);
            flag = s1.contains(s2);
        } else if (logic.equals(LOGIC_LIKE_LEFT)) {
            String s1 = Convert.toStr(obj);
            String s2 = Convert.toStr(value);
            flag = s1.startsWith(s2);
        } else if (logic.equals(LOGIC_LIKE_RIGHT)) {
            String s1 = Convert.toStr(obj);
            String s2 = Convert.toStr(value);
            flag = s1.endsWith(s2);
        } else if (logic.equals(LOGIC_EQUALS)) {
            Class<?> tClass = obj.getClass();
            Object temp = Convert.convert(tClass, value);

            flag = temp.equals(obj);
        } else {
            flag = validEqual(obj, value);
        }

        return flag;
    }

    private boolean validEqual(Object o1, Object o2) {
        int flag = 0;
        if (o1 instanceof Long) {
            Long temp1 = (Long) o1;
            Long temp2 = Convert.convert(Long.class, o2);
            flag = temp1.compareTo(temp2);
        } else if (o1 instanceof Integer) {
            Integer temp1 = (Integer) o1;
            Integer temp2 = Convert.convert(Integer.class, o2);
            flag = temp1.compareTo(temp2);
        } else if (o1 instanceof Double) {
            Double temp1 = (Double) o1;
            Double temp2 = Convert.convert(Double.class, o2);
            flag = temp1.compareTo(temp2);
        } else if (o1 instanceof Float) {
            Float temp1 = (Float) o1;
            Float temp2 = Convert.convert(Float.class, o2);
            flag = temp1.compareTo(temp2);
        } else if (o1 instanceof BigDecimal) {
            BigDecimal temp1 = (BigDecimal) o1;
            BigDecimal temp2 = Convert.convert(BigDecimal.class, o2);
            flag = temp1.compareTo(temp2);
        } else if (o1 instanceof BigInteger) {
            BigInteger temp1 = (BigInteger) o1;
            BigInteger temp2 = Convert.convert(BigInteger.class, o2);
            flag = temp1.compareTo(temp2);
        } else if (o1 instanceof Character) {
            Character temp1 = (Character) o1;
            Character temp2 = Convert.convert(Character.class, o2);
            flag = temp1.compareTo(temp2);
        } else if (o1 instanceof Short) {
            Short temp1 = (Short) o1;
            Short temp2 = Convert.convert(Short.class, o2);
            flag = temp1.compareTo(temp2);
        } else if (o1 instanceof Date) {
            Date temp1 = (Date) o1;
            Date temp2 = Convert.convert(Date.class, o2);
            flag = temp1.compareTo(temp2);
        } else if (o1 instanceof String) {
            String temp1 = (String) o1;
            String temp2 = Convert.convert(String.class, o2);
            flag = temp1.compareTo(temp2);
        }

        if (logic.equals(LOGIC_GE)) {
            return flag >= 0;
        } else if (logic.equals(LOGIC_LE)) {
            return flag <= 0;
        } else if (logic.equals(LOGIC_EQUALS)) {
            return flag == 0;
        } else if (logic.equals(LOGIC_LT)) {
            return flag < 0;
        } else if (logic.equals(LOGIC_GT)) {
            return flag > 0;
        }

        return false;
    }

}